home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Networking / OTStreamLogViewer / FileLogging.c next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  7.3 KB  |  277 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        FileLogging.c
  3.  
  4.     Contains:    File logging engine for OTStreamLogViewer.
  5.  
  6.     Written by: Quinn "The Eskimo!"    
  7.  
  8.     Copyright:    Copyright © 1998-1999 by Apple Computer, Inc., All Rights Reserved.
  9.  
  10.                 You may incorporate this Apple sample source code into your program(s) without
  11.                 restriction. This Apple sample source code has been provided "AS IS" and the
  12.                 responsibility for its operation is yours. You are not permitted to redistribute
  13.                 this Apple sample source code as "Apple sample source code" after having made
  14.                 changes. If you're going to re-distribute the source, we require that you make
  15.                 it clear in the source that the code was descended from Apple sample source
  16.                 code, but that you've made changes.
  17.  
  18.     Change History (most recent first):
  19.                 7/23/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  20.                 
  21.  
  22. */
  23. #include <Devices.h>
  24. #define qDebug 1
  25.  
  26. /////////////////////////////////////////////////////////////////////
  27. // Standard C stuff.
  28.  
  29. #import <stdio.h>
  30.  
  31. /////////////////////////////////////////////////////////////////////
  32. // Pick up standard OT APIs.
  33.  
  34. #include <OpenTransport.h>
  35.  
  36. /////////////////////////////////////////////////////////////////////
  37. // Pick up the low-level OT APIs.
  38.  
  39. #include <OTDebug.h>
  40.  
  41. /////////////////////////////////////////////////////////////////////
  42. // Pick up toolbox stuff.
  43.  
  44. #include <TextUtils.h>
  45. #include <Errors.h>
  46.  
  47. /////////////////////////////////////////////////////////////////////
  48. // Pick up our resource definitions.
  49.  
  50. #include "StreamLogResources.h"
  51.  
  52. /////////////////////////////////////////////////////////////////////
  53. // Pick up our own prototypes.
  54.  
  55. #include "FileLogging.h"
  56.  
  57. /////////////////////////////////////////////////////////////////////
  58. // OTDebugStr is not defined in any OT header files, but it is
  59. // exported by the libraries, so we define the prototype here.
  60.  
  61. extern pascal void OTDebugStr(const char* str);
  62.  
  63. /////////////////////////////////////////////////////////////////////
  64.  
  65. static OSStatus FSWriteQAtLEOF(SInt16 fileRefNum, SInt32 count, void *buffer)
  66.     // Writes the count bytes at buffer to the end of fileRefNum.
  67. {
  68.     ParamBlockRec pb;
  69.  
  70.     pb.ioParam.ioRefNum = fileRefNum;
  71.     pb.ioParam.ioBuffer = buffer;
  72.     pb.ioParam.ioReqCount = count;
  73.     pb.ioParam.ioPosMode = fsFromLEOF;
  74.     pb.ioParam.ioPosOffset = 0;
  75.     
  76.     return PBWriteSync(&pb);
  77. }
  78.  
  79. /////////////////////////////////////////////////////////////////////
  80. // File Logging Stuff
  81.  
  82. static SInt16 gLogFileRefNum = 0;
  83.     // The file refnum of the log file, or 0 if logging
  84.     // is not active.
  85.  
  86. static char gLogAssemblyBuffer[10240];
  87.     // A temporary buffer used to assemble log text 
  88.     // we're about to write to the file.
  89.  
  90. static UInt32 gTicksOfLastFileWrite;
  91.     // The TickCount time at which we last wrote to the file.
  92.     // If TickCount is more than this value plus
  93.     // kTicksPerFlush, we need to flush the file now.
  94.  
  95. enum {
  96.     kTicksPerFlush = 6,
  97.         // Number of ticks from when we write to a file to when
  98.         // we perform a FlushFile to make sure it gets to the disk.
  99.  
  100.     kLogFileCleanTicks = (UInt32) -(kTicksPerFlush+1)
  101.         // When the file is flushed we set gTicksOfLastFileWrite
  102.         // to this value to prevent further writes from happening.
  103.         // This corresponds to "far in the future".    
  104. };
  105.  
  106. static char kStartFileLogString[] = "Sequence\tFlags\tFlags (as number)\tTime (ms)\tReal Time\tModule ID\tStream ID\tMessage\r";
  107.     // When we start logging, we write this line to the file
  108.     // to give the user some idea of the what each column means.
  109.     
  110. extern OSStatus StartFileLogging(void)
  111.     // See comment in interface part.
  112. {
  113.     OSStatus err;
  114.     Str255 logFileName;
  115.     FSSpec logFile;
  116.     
  117.     OTAssert("StartFileLogging: We're already logging!", gLogFileRefNum == 0);
  118.  
  119.     gTicksOfLastFileWrite = kLogFileCleanTicks;
  120.  
  121.     // Open up the log file, creating it if necessary.
  122.         
  123.     GetIndString(logFileName, rMiscStrings, strLogFileName);
  124.     err = FSMakeFSSpec(-1, fsRtDirID, logFileName, &logFile);
  125.     if (err == fnfErr) {
  126.         err = noErr;
  127.     }
  128.     if (err == noErr) {
  129.         (void) FSpCreate(&logFile, 'R*ch', 'TEXT', 0);
  130.         err = FSpOpenDF(&logFile, fsWrPerm, &gLogFileRefNum);
  131.         if (err != noErr) {
  132.             gLogFileRefNum = 0;
  133.         }
  134.     }
  135.     
  136.     // Write the header to the file.
  137.     
  138.     if (err == noErr) {
  139.         err = FSWriteQAtLEOF(gLogFileRefNum, OTStrLength(kStartFileLogString), kStartFileLogString);
  140.     }    
  141.     
  142.     // Clean up.
  143.     
  144.     if (err != noErr) {
  145.         if ( gLogFileRefNum != 0 ) {
  146.             StopFileLogging();
  147.         }
  148.     }
  149.     
  150.     return err;
  151. }
  152.  
  153. enum {
  154.     kFlagsToStringBufferSize = 50
  155.         // flagStr must point to a buffer of at least 50 characters.
  156. };
  157.  
  158. static void FlagsToString(char flags, char *flagStr)
  159.     // Create a verbose string that represents the various
  160.     // flag bits in flags.
  161. {
  162.     flagStr[0] = 0;
  163.  
  164.     if ((flags & SL_TRACE) != 0) {
  165.         OTStrCat(flagStr, "Trace ");
  166.     }
  167.     if ((flags & SL_ERROR) != 0) {
  168.         OTStrCat(flagStr, "Error ");
  169.     }
  170.     if ((flags & SL_CONSOLE) != 0) {
  171.         OTStrCat(flagStr, "Console ");
  172.     }
  173.     
  174.     if ((flags & SL_FATAL) != 0) {
  175.         OTStrCat(flagStr, "Fatal ");
  176.     }
  177.     if ((flags & SL_NOTIFY) != 0) {
  178.         OTStrCat(flagStr, "Notify ");
  179.     }
  180.     if ((flags & SL_WARN) != 0) {
  181.         OTStrCat(flagStr, "Warning ");
  182.     }
  183.     if ((flags & SL_NOTE) != 0) {
  184.         OTStrCat(flagStr, "Notice ");
  185.     }
  186.     
  187.     // Remove the trailing space.
  188.     
  189.     if ( flagStr[0] != 0 ) {
  190.         flagStr[ OTStrLength(flagStr) - 1 ] = 0;
  191.     }
  192. }
  193.  
  194. extern char *LogEntryToCString(LogEntryPtr thisEntry)
  195.     // See comment in interface part.
  196. {
  197.     Str255 dateStr;
  198.     Str255 timeStr;
  199.     char   flagStr[kFlagsToStringBufferSize];
  200.  
  201.     OTAssert("LogEntryToCString: paramErr", thisEntry != nil);
  202.     
  203.     FlagsToString(thisEntry->fLogHeader.flags, flagStr);
  204.  
  205.     // ltime is generated by calling OTGetTimeStamp and converting
  206.     // the result to milliseconds using OTTimeStampInMilliseconds.
  207.     
  208.     // ttime is the result of the low-memory global Time, which
  209.     // is the same as the result of GetDateTime.
  210.  
  211.     DateString(thisEntry->fLogHeader.ttime, shortDate, dateStr, nil);
  212.     TimeString(thisEntry->fLogHeader.ttime, true, timeStr, nil);
  213.  
  214.     sprintf(gLogAssemblyBuffer, "%ld\t%s\t0x%02x\t0x%08x\t%#s %#s\t%d\t%d\t%s\r",
  215.             thisEntry->fLogHeader.seq_no,
  216.             flagStr,
  217.             thisEntry->fLogHeader.flags,
  218.             thisEntry->fLogHeader.ltime,
  219.             dateStr,
  220.             timeStr,
  221.             thisEntry->fLogHeader.mid,
  222.             thisEntry->fLogHeader.sid,
  223.             (char *) thisEntry + sizeof(LogEntry)
  224.         );
  225.     return gLogAssemblyBuffer;
  226. }
  227.  
  228. extern void RecordLogEntryToFile(LogEntryPtr thisEntry)
  229.     // See comment in interface part.
  230. {
  231.     OSStatus junk;
  232.     
  233.     if ( gLogFileRefNum != 0 ) {
  234.     
  235.         (void) LogEntryToCString(thisEntry);
  236.         
  237.         junk = FSWriteQAtLEOF(gLogFileRefNum, OTStrLength(gLogAssemblyBuffer), gLogAssemblyBuffer);
  238.         OTAssert("RecordLogEntryToFile: Error writing log entry", junk == noErr);
  239.         
  240.         gTicksOfLastFileWrite = TickCount();
  241.     }
  242. }
  243.  
  244. extern void FileLoggingIdle(void)
  245.     // See comment in interface part.
  246. {
  247.     OSStatus junk;
  248.     ParamBlockRec pb;
  249.  
  250.     if ( gLogFileRefNum != 0 ) {
  251.         if ( TickCount() > gTicksOfLastFileWrite + kTicksPerFlush ) {
  252.             pb.ioParam.ioRefNum = gLogFileRefNum;
  253.             junk = PBFlushFileSync(&pb);
  254.             OTAssert("DoIdle: FlushFile returned an error", junk == noErr);
  255.             gTicksOfLastFileWrite = kLogFileCleanTicks;
  256.         }
  257.     }
  258. }
  259.  
  260. extern Boolean FileLoggingActive(void)
  261.     // See comment in interface part.
  262. {
  263.     return gLogFileRefNum != 0;
  264. }
  265.  
  266. extern void StopFileLogging(void)
  267.     // See comment in interface part.
  268. {
  269.     OSStatus junk;
  270.     
  271.     OTAssert("StopFileLogging: We're not logging!", gLogFileRefNum != 0);
  272.     
  273.     junk = FSClose(gLogFileRefNum);
  274.     OTAssert("StopFileLogging: Could not close log file", junk == noErr);
  275.     gLogFileRefNum = 0;
  276. }
  277.